package com.syx.job.Handler;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.syx.common.redis.Service.RedisService;
import com.syx.commoncore.Constant.CacheConstant;
import com.syx.commoncore.Constant.Constant;
import com.syx.job.Mapper.ExamMapper;
import com.syx.job.Mapper.UserExamMapper;
import com.syx.job.Mapper.UserSubmitMapper;
import com.syx.job.Model.exam.Exam;
import com.syx.job.Model.message.Message;
import com.syx.job.Model.message.MessageText;
import com.syx.job.Model.message.VO.MessageTextVO;
import com.syx.job.Model.user.UserScore;
import com.syx.job.Service.IMessageService;
import com.syx.job.Service.IMessageTextService;
import com.xxl.job.core.handler.annotation.XxlJob;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Component
public class ExamXxlJob {

    @Resource
    ExamMapper examMapper;

    @Resource
    RedisService redisService;

    @Resource
    UserSubmitMapper userSubmitMapper;

    @Resource
    IMessageTextService iMessageTextService;


    @Resource
    IMessageService iMessageService;

    @Resource
    UserExamMapper userExamMapper;


    @XxlJob("examListOrganizeHandler")
    public void examListOrganizeHandler()  {
        log.info("***************examListOrganizeHandler");
        System.out.println("examListOrganizeHandler");
        // TODO 业务逻辑找到哪些是应该更新缓存将已经完成的竞赛去除掉，将过了时间的竞赛从未开始竞赛删除去，变成历史竞赛
        /// 查询历史竞赛：结束时间小于当前时间
        List<Exam> finishedExamList = examMapper.selectList(new LambdaQueryWrapper<Exam>()
                .select(Exam::getExamId, Exam::getTitle, Exam::getStartTime, Exam::getEndTime,Exam::getStatus)
                .lt(Exam::getEndTime, LocalDateTime.now())
                .eq(Exam::getStatus, Constant.TRUE)
                .orderByDesc(Exam::getCreateTime));
        refreshCache(finishedExamList,CacheConstant.EXAM_HISTORY_LIST);


        /// 结束时间晚于当前时间，那就是还在进行或者还没开始的竞赛
        List<Exam>  unFinshExamList = examMapper.selectList(new LambdaQueryWrapper<Exam>()
                .select(Exam::getExamId, Exam::getTitle, Exam::getStartTime, Exam::getEndTime,Exam::getStatus)
                .gt(Exam::getEndTime, LocalDateTime.now())
                .eq(Exam::getStatus, Constant.TRUE)
                .orderByDesc(Exam::getCreateTime));
        refreshCache(unFinshExamList,CacheConstant.EXAM_UNFINISHED_LIST);

    }

    @XxlJob("examResultHandler")
    public void examResultHandler(){
        //在每天定时给成员发送消息
        //统计前一天的数据给用户存起来
        LocalDateTime now=LocalDateTime.now();
        //前一天的时间
        LocalDateTime minusDateTime=now.minusDays(1);
        List<Exam> examList  = examMapper.selectList(new LambdaQueryWrapper<Exam>()
                .select(Exam::getExamId, Exam::getTitle)
                .eq(Exam::getStatus, Constant.TRUE)
                .gt(Exam::getEndTime, minusDateTime)
                .lt(Exam::getEndTime, now));
        //获取到examId进行统计
        //如果没有比赛
        if (CollectionUtil.isEmpty(examList)){
            return;
        }
        Set<Long> examIds = examList.stream().map(Exam::getExamId).collect(Collectors.toSet());
        //根据examId进行查找对应的人的分数
        List<UserScore> userScores = userSubmitMapper.selectUserScoreList(examIds);
        //通过examId进行查找对应的userScore
        Map<Long, List<UserScore>> userScoreList  = userScores.stream().collect(Collectors.groupingBy(UserScore::getExamId));
        createMessages(examList ,userScoreList);

    }

    private void createMessages(List<Exam> examList, Map<Long, List<UserScore>> userScoreList) {
        //每个message有不同的接收人
        List<Message> messageList=new ArrayList<>();
        List<MessageText> messageTextList=new ArrayList<>();
        for (Exam exam : examList){
            Long oneExamId = exam.getExamId();
            //某 比赛中每个人的分数
            List<UserScore> individualUserScores = userScoreList.get(oneExamId);
            int total=individualUserScores.size();
            int examRank=1;
            //不同的内容

            for (UserScore userScore:individualUserScores){
                userScore.setExamRank(examRank);
                String messageTitle=exam.getTitle();
                String msgContent = "您所参与的竞赛：" + exam.getTitle()
                        + "，本次参与竞赛一共" + total + "人， 您排名第"  + examRank + "名！";
                MessageText messageText=new MessageText();
                messageText.setMessageTitle(messageTitle);
                messageText.setMessageContent(msgContent);
                //写入创建的用户
                messageText.setCreateBy(Constant.SYSTEM_USER_ID);
                messageTextList.add(messageText);
                Message message=new Message();
                message.setSendId(Constant.SYSTEM_USER_ID);
                message.setRecId(userScore.getUserId());
                message.setCreateBy(Constant.SYSTEM_USER_ID);
                messageList.add(message);
                examRank++;
            }
            userExamMapper.updateUserScoreAndRank(individualUserScores);
            //一个比赛对应一个
            redisService.rightPushAll(getExamRankListKey(exam.getExamId()),individualUserScores);   


        }
        //批量插入数据
        iMessageTextService.batchInsert(messageTextList);
        //插入后才会生成
        Map<String,MessageTextVO> messageTextVOMap=new HashMap<>();
        for (int i = 0; i < messageTextList.size(); i++) {
            Message messageUpdateTextId =messageList.get(i);
            //赋值textId
            MessageText messageText= messageTextList.get(i);
            messageUpdateTextId.setTextId(messageText.getTextId());
            MessageTextVO messageTextVO=new MessageTextVO();
            BeanUtil.copyProperties(messageText,messageTextVO);
            //redis中的key
            String msgDetailKey = getMsgDetailKey(messageText.getTextId());
            messageTextVOMap.put(msgDetailKey,messageTextVO);
            //将textId和messageTitle等放入redis
        }
        //封装好keyvalue后插入redis
        redisService.multiSet(messageTextVOMap);
        iMessageService.batchInsert(messageList);
        Map<Long, List<Message>> recIdMapMessage = messageList.stream().collect(Collectors.groupingBy(Message::getRecId));
        Iterator<Map.Entry<Long, List<Message>>> iterator = recIdMapMessage.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry<Long, List<Message>> next = iterator.next();
            Long recId = next.getKey();
            List<Message> value = next.getValue();
            String userMsgListKey = getUserMsgListKey(recId);
            List<Long> TextId = value.stream().map(Message::getTextId).toList();
            redisService.rightPushAll(userMsgListKey,TextId);

        }


    }

    //获取排名
    private String getExamRankListKey(Long examId) {
        return CacheConstant.EXAM_RANK_LIST + examId;
    }

    public void refreshCache(List<Exam> examList,String examListKey) {

        if (CollectionUtil.isEmpty(examList)) {
            return;
        }
        Map<String, Exam> examMap = new HashMap<>();
        List<Long> examIdList = new ArrayList<>();
        for (Exam exam : examList) {
            examMap.put(getDetailKey(exam.getExamId()), exam);
            examIdList.add(exam.getExamId());
        }

        // 写入 Redis 缓存
        redisService.multiSet(examMap);  // 缓存每个竞赛的详细信息
        redisService.deleteObject(examListKey);  // 删除旧缓存
        redisService.rightPushAll(examListKey, examIdList);  // 推送新的竞赛 ID 列表
    }
    private String getDetailKey(Long examId) {
        return CacheConstant.EXAM_DETAIL + examId;
    }
    private String getUserMsgListKey(Long userId) {
        return CacheConstant.USER_MESSAGE_LIST + userId;
    }

    private String getMsgDetailKey(Long textId) {
        return CacheConstant.MESSAGE_DETAIL + textId;
    }
}
